package org.myOrg.spetrum.io;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * right foramt is such as: param: 5 5 5 5 5 5 failed: 3 3 4 2 2 2 passed: 2 2 2
 * 2 2 2
 * 
 * @author Xintao Niu
 * 
 */

public class ValidateImplement implements ValidateFormat {

	public static final String PARAMSIGN = "param:";
	public static final String PASSEDSIGN = "passed:";
	public static final String FAILEDSIGN = "failed:";

	public static final String FORMATGOOD = "the format is good!";
	public static final String NOFAILEDTESTS = "no failed tests!";
	public static final String NOPASSEDTESTS = "no passed tests!";
	public static final String NOTHING = "there is nothing!";
	public static final String NOPARAM = "no paramater!";
	public static final String TESTLENTHERROR = "one test length is not eqaul as the param!";
	public static final String TESTVALUEOVER = "one param value is over the scope of the param!";

	private String description;
	private int[] param;
	private BufferedReader in;
	private List<int[]> passedTests;
	private List<int[]> failedTests;

	private String filePath;

	public ValidateImplement() {
		passedTests = new ArrayList<int[]>();
		failedTests = new ArrayList<int[]>();
	}

	/**
	 * @return the passedTests
	 */
	public List<int[]> getPassedTests() {
		return passedTests;
	}

	/**
	 * @return the failedTests
	 */
	public List<int[]> getFailedTests() {
		return failedTests;
	}

	@Override
	public boolean validate(String filePath) {
		// TODO Auto-generated method stub
		this.filePath = filePath;
		try {
			validateSystemReader(filePath);
			validateParam();
			validateFailedTests();
			validatePassedTests();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			this.description = e.getMessage();
			return false;
		}
		description = FORMATGOOD;
		return true;
	}

	private void validateFailedTests() throws Exception {
		// read the param
		String oneLine = getOneLine();
		if (oneLine == null) {
			throw new Exception(NOFAILEDTESTS);
		}
		if (oneLine.equals(FAILEDSIGN)) {
			while ((oneLine = getOneLine()) != null) {
				if (oneLine.equals(PASSEDSIGN))
					break;
				int[] temp = changeStringToIntArray(oneLine);
				validateOneTest(temp);
				failedTests.add(temp);
			}
			if (failedTests.size() == 0)
				throw new Exception(NOFAILEDTESTS);

		} else {
			throw new Exception(NOFAILEDTESTS);
		}
	}

	private void validateOneTest(int[] temp) throws Exception {
		if (temp.length != param.length)
			throw new Exception(TESTLENTHERROR);
		for (int j = 0; j < temp.length; j++) {
			if (temp[j] >= param[j]) {
				throw new Exception(TESTVALUEOVER);
			}
		}
	}

	private void validatePassedTests() throws Exception {
		String oneLine;
		while ((oneLine = getOneLine()) != null) {
			int[] temp = changeStringToIntArray(oneLine);
			validateOneTest(temp);
			passedTests.add(temp);
		}
		if (passedTests.size() == 0)
			throw new Exception(NOPASSEDTESTS);
	}

	private void validateParam() throws Exception {
		// read the param
		String oneLine = getOneLine();
		if (oneLine == null) {
			throw new Exception(NOTHING);
		}
		if (oneLine.equals(ValidateImplement.PARAMSIGN)) {
			String param = getOneLine();
			this.param = changeStringToIntArray(param);

		} else {
			throw new Exception(NOPARAM);
		}
	}

	private int[] changeStringToIntArray(String param) {
		int[] result;
		StringTokenizer itr = new StringTokenizer(param);
		result = new int[itr.countTokens()];
		int i = 0;
		while (itr.hasMoreTokens()) {
			result[i] = Integer.parseInt(itr.nextToken());
			i++;
		}
		return result;
	}

	private String getOneLine() throws Exception {
		String oneLine = "";
		while (oneLine.length() == 0) {
			oneLine = in.readLine();
			if (oneLine == null) {
				break;
			}
		}
		return oneLine;
	}

	private void validateSystemReader(String filePath)
			throws FileNotFoundException {
		in = new BufferedReader(new FileReader(filePath));
	}

	@Override
	public String getJudgeDescription() {
		// TODO Auto-generated method stub
		return this.description;
	}

	/**
	 * @return the param
	 */
	public int[] getParam() {
		return param;
	}

	@Override
	public String getValidatePath() {
		// TODO Auto-generated method stub
		return filePath;
	}

}
